package concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DemoHashMap {

	private static ConcurrentMap<String, String> map = new ConcurrentHashMap<String, String>();// 它本身是线程安全的，但是在下面的应用中并不是一个原子操作

	private static String[] keys = { "hongxingfan", "wenxiubi", "guangweicao", "xiaoyanwang", "aaa", "bbb",
	        "ccc", "ddd", "eee", "fff" };
	private static String[] values = { "27", "25", "28", "26", "1", "2", "3", "4", "5", "6" };

	public static void main(String[] args) {

		ExecutorService exec = Executors.newCachedThreadPool();
		exec.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
				int j = 10;
				while (j-- > 0) {
					int i = (int) (Math.random() * 10);
					synchronized (this) {
						if (!map.containsKey(keys[i])) {
							System.out.println(Thread.currentThread().getName() + "put:" + keys[i] + "-->"
							        + values[i]);
							map.put(keys[i], values[i]);
							Thread.sleep(500);
						}
					}
				}
				return null;
			}
		});
		exec.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
				int j = 10;
				while (j-- > 0) {
					int i = (int) (Math.random() * 10);
					synchronized (this) { // 所以这里需要加锁，保证containsKey和put是一个原子操作
						if (!map.containsKey(keys[i])) {
							System.out.println(Thread.currentThread().getName() + "put:" + keys[i] + "-->"
							        + values[i]);
							map.put(keys[i], values[i]);
							Thread.sleep(200);
						}
					}
				}
				return null;
			}
		});
		exec.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
				int j = 10;
				while (j-- > 0) {
					int i = (int) (Math.random() * 10);
					synchronized (this) {
						if (!map.containsKey(keys[i])) {
							System.out.println(Thread.currentThread().getName() + "put:" + keys[i] + "-->"
							        + values[i]);
							map.put(keys[i], values[i]);
							Thread.sleep(100);
						}
					}
				}
				return null;
			}
		});
		exec.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
				while (true) {
					int i = (int) (Math.random() * 10);
					synchronized (this) {
						if (map.containsKey(keys[i])) {
							System.out.println(Thread.currentThread().getName() + "remove:" + keys[i] + "-->"
							        + map.remove(keys[i]));
							Thread.sleep(100);
						}
					}
				}
			}
		});
	}
}
